#pragma once
#include "UltimatePhysX3Precompiled.h"
#include "UltimatePhysX3Scene.h"
#include "UltimatePhysX3ContactReport.h"

UltimatePhysX3Scene::UltimatePhysX3Scene(PxScene *scene,PxPhysics* physics)
{
	mPhysics = physics;
	mPxScene = scene;
}


UltimatePhysX3Scene::~UltimatePhysX3Scene(void)
{

}

bool UltimatePhysX3Scene::initScene()
{
	

	// Create the default material
	mMaterial = mPhysics->createMaterial(0.5f, 0.5f, 0.1f);    //static friction, dynamic friction, restitution
	if(!mMaterial)
		Ogre::LogManager::getSingletonPtr()->logMessage(Ogre::LML_CRITICAL,"createMaterial failed!");

	mPxScene->setSimulationEventCallback(&PhysX3ContactReport);



	// No collision between the sword and its body
	PxSetGroupCollisionFlag(1,1, false);
	// sword vs penguin
	PxSetGroupCollisionFlag(1,2, false);
	// sword vs projectiles
	PxSetGroupCollisionFlag(1,3, true);
	// sword vs enemies
	PxSetGroupCollisionFlag(1,4, false);

	// penguins
	PxSetGroupCollisionFlag(2,2, false);
	// penguin vs projectiles
	PxSetGroupCollisionFlag(2,3, true);
	// penguin vs enemies
	PxSetGroupCollisionFlag(2,4, false);

	// projectiles
	PxSetGroupCollisionFlag(3,3, false);
	// projectiles vs enemies
	PxSetGroupCollisionFlag(3,4, false);

	PxSetGroupCollisionFlag(1,9, true);
	PxSetGroupCollisionFlag(6,9, false);

	return true;
}
UltimatePhysicsActor * UltimatePhysX3Scene::createPhysicsActor(UltimatePhysicsActorDesc *desc,Ogre::Vector3 position, Ogre::Quaternion orientation, bool isKinematic, bool isStatic, int collisionGroup, int weight)
{

	UltimatePhysX3Actor * ultimateActor = new UltimatePhysX3Actor();
	PxRigidDynamic * actorDesc =((UltimatePhysX3ActorDesc*) desc)->getPxActorDesc();
	ultimateActor->setPxActor(actorDesc);


	if(isKinematic)
	{
		ultimateActor->setKinematic(true);
	}

	PxSetGroup(*actorDesc,collisionGroup);


	PxTransform newPose;

	PxTransform pose= actorDesc->getGlobalPose();
	
	newPose.p = PxVec3(position.x, position.y , position.z);
	newPose.q = PxQuat(orientation.x,orientation.y,orientation.z,orientation.w);

	actorDesc->setGlobalPose(newPose);

	

	
	actorDesc->userData = ultimateActor;

	PxRigidBodyExt::updateMassAndInertia(*actorDesc,weight);


	mPxScene->addActor(*actorDesc);

	return (UltimatePhysicsActor*)ultimateActor;

}
UltimatePhysicsActorDesc * UltimatePhysX3Scene::createPhysicsActorDesc()
{
	

	PxRigidDynamic* actor = mPhysics->createRigidDynamic(PxTransform(PxVec3(0,0,0)));
	

	return (UltimatePhysicsActorDesc*)new UltimatePhysX3ActorDesc(actor,mMaterial);
}

void UltimatePhysX3Scene::destroyPhysicsActor(UltimatePhysicsActor* actor)
{
	PxActor * nxActor = ((UltimatePhysX3Actor*)actor)->getPxActor();
	actor->setUserData(NULL);
	mPxScene->removeActor(*nxActor);
}

void UltimatePhysX3Scene::createPhysicsPlane(int height,int collisionGroup)
{
	/*PxRigidStatic* plane = PxCreatePlane(*mPhysics, PxPlane(PxVec3(0,1,0), height), *mMaterial);
	if (!plane)
		Ogre::LogManager::getSingletonPtr()->logMessage(Ogre::LML_CRITICAL,"create shape failed!");
	mPxScene->addActor(*plane);*/
	
}

void UltimatePhysX3Scene::setGravity(int x, int y, int z)
{
	mPxScene->setGravity(PxVec3(x,y,z));
}


void UltimatePhysX3Scene::stepSimulation(float elapsedTime)
{
	mPxScene->simulate(elapsedTime);

	while(mPxScene->fetchResults(true));
}


void UltimatePhysX3Scene::addContactListener(UltimatePhysicsContactListener* listener)
{
	PhysX3ContactReport.addContactListener(listener);
}